<?php

/**
 * User: day
 * Date: 2018/09/04
 * Time: 10:31
 * Desc:
 * 調用創建帳號時(method=lg)，actype=帶入0即可創建測試帳號的
 * 接入的游戏有：AG真人視訊、AG電子、捕魚、養魚（买鱼）、XIN、Yoplay
 * 獲取數據的接口對應如下:
 *  【電子遊戲API】AG電子、XIN
 *  【Yoplay API】Yoplay
 *  【視訊遊戲API】AG真人視訊
 *  【捕魚數據獲取API】捕魚、養魚（买鱼） (有另外的捕鱼文档)
 */

namespace App\Services\ThirdAPI;

use common\utils\RedisKeys;
use App\Models\Order;
use App\Models\PlayType;
use Illuminate\Support\Facades\DB;
use App\Models\Game;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;
use common\utils\SysCode;

class AGAPIService
{
    protected $apiName = 'AG';
    // 對應的線別
    public $cagent;
    // 语言 lang_cns 簡體中文, lang_cnr 繁體中文, lang_english 英文
    public $language;
    // 请求的 api 地址
    public $api_url;
    // AG 的 md5 明码
    public $api_md5_key;

    // public $gi_api;
    // public $gci_api;
    // public $desKey;
    // public $md5EncryptKey;
    // public $ftpUrl;
    // public $ftpName;
    // public $ftpPasswd;
    // public $api_cagent;
    // public $api_url2;

    public static $ErrorMsg = [
        0 => '成功',
        44000 => 'Key 错误,请检查明码及加密顺序是否正确',
        64010 => '查询额度成功',
        61003 => '产品 ID 或 CATENT 不存在',
        60001 => '不存在该用户',
        61004 => '指令执行错误',
        61001 => '查詢請求時間被限制',
        61002 => '参数缺失,请检查是否参数都有正确带入',
        61005 => '代理商不存在',
    ];

    /**
     * 统计请求方法封装
     */
    public function request($url, $method, $data, $header = "")
    {
        $hashStr = '';
        foreach ($data as $key => $value) {
            $hashStr .= $value;
        }
        $data['key'] = md5($hashStr . $this->api_md5_key);
        Log::info("AG API请求: {$url}, data: " . json_encode($data));
        $response = GameApiService::request($url, $method, $data);
        if (!$response->isOk) {
            $msg = "AG 获取注单失败，AGAPIService->request: {$url}\ndata: " . json_encode($data) . "\nhttp code: {$response->getStatusCode()}";
            Log::error($msg);
            return error_exit(SysCode::INTERNAL_SERVER_ERROR, $msg);
        }
        return $response;
    }

    /**
     * 捕鱼请求
     */
    public function fishRequest($url, $method, $data)
    {
        $hashStr = '';
        foreach ($data as $key => $value) {
            if ($key != 'hunted') {
                $hashStr .= $value;
            }
        }
        $data['sessionkey'] = md5($hashStr . $this->api_md5_key);
        Log::info("AG fishRequest API请求: {$url}, data: " . json_encode($data));
        $response = GameApiService::request($url, $method, $data);
        if (!$response) {
            $msg = "AG 获取注单失败，AGAPIService->fishRequest: {$url}\ndata: " . json_encode($data) . "\nhttp code: {$response->getStatusCode()}";
            Log::error($msg);
            return error_exit(SysCode::INTERNAL_SERVER_ERROR, $msg);
        }
        return $response;
    }

    /**
     * 拉取注单统一入口(不同游戏参数拼装不同,单独处理与rpc交互参数)
     */
    public function getAGOrders($gameType, $startTime, $endTime)
    {
        $result = [];
        switch ($gameType) {
            case 'slot':
                $result = $this->getSlotOrders($startTime, $endTime);
                break;
            case 'yoplay':
                $result = $this->getYoPlayOrders($startTime, $endTime);
                break;
            case 'fish':
                $result = $this->getFishOrders($startTime, $endTime);
                break;
            case 'buyfish':
                $result = $this->getBuyFish($startTime, $endTime);
                break;
            case 'video':
                $result = $this->getVideoOrders($startTime, $endTime);
                break;
        }
        return $result;
    }

    /**
     * 获取电子订单数据
     * 美东时间
     * desc: 查詢時間以订单派彩時間為准
     */
    public function getSlotOrders($startTime, $endTime, $page = 1, $perpage = 500)
    {
        $url = config('app.rpcserver') . "/api/getOrders";
        $res = GameApiService::request($url, 'get', [
            'type' => 'slot',
            'api_name' => 'AG',
            'startdate' => date("Y-m-d H:i:s", $startTime - 12 * 60 * 60),
            'enddate' => date("Y-m-d H:i:s", $endTime - 12 * 60 * 60),
            'page' => $page,
            'perpage' => $perpage
        ]);
        $result = [];
        $code = $res['Code'] ?? $res['info'];
        if ($code == 0 && $res['addition']['total'] > 0) {
            if (count($res['row']) == 1) {
                $tmp = $res['row'];
                $res['row'] = [];
                $res['row'][0] = $tmp;
            }
            foreach ($res['row'] as $key => $value) {
                $subData = [];
                $result[] = $value['@attributes'];
            }
            // 拉取剩下的注单
            if ($res['addition']['total'] > $page * $perpage) {
                $result = array_merge($result, $this->getSlotOrders($startTime, $endTime, $page + 1));
            }
        } else {
            $msg = "AGAPIService->getSlotOrders 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code];
            Log::error($msg);
            error_exit($msg);
        }
        return $result;
    }

    /**
     * 获取 YoPlay 电子订单数据
     * desc: 查詢時間以订单派彩時間為准
     */
    public function getYoPlayOrders($startTime, $endTime, $page = 1, $perpage = 500)
    {
        $url = config('app.rpcserver') . "/api/getOrders";
        $res = GameApiService::request($url, 'get', [
            'type' => 'yoplay',
            'api_name' => 'AG',
            'startdate' => date("Y-m-d H:i:s", $startTime - 12 * 60 * 60),
            'enddate' => date("Y-m-d H:i:s", $endTime - 12 * 60 * 60),
            'page' => $page,
            'perpage' => $perpage
        ]);
        $res = $res['data'];
        $result = [];
        if ($res) {
            // todo test, add to sql
            $code = $res['info'];
            if ($code == 0) {
                if (count($res['row']) == 1) {
                    $tmp = $res['row'];
                    $res['row'] = [];
                    $res['row'][0] = $tmp;
                }
                foreach ($res['row'] as $key => $value) {
                    $subData = [];
                    $result[] = $value['@attributes'];
                }
                // 拉取剩下的注单
                if ($res['addition']['total'] > $page * $perpage) {
                    $result = array_merge($result, $this->getYoPlayOrders($startTime, $endTime, $page + 1));
                }
            } else {
                $msg = "AGAPIService->getYoPlayOrders 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code];
                Log::error($msg);
                error($msg);
            }
        }
        return $result;
    }

    /**
     * 获取视讯订单数据
     * desc: 查詢時間以订单派彩時間為准
     */
    public function getVideoOrders($startTime, $endTime, $page = 1, $perpage = 500)
    {
        $url = config('app.rpcserver') . "/api/getOrders";
        $res = GameApiService::request($url, 'get', [
            'type' => 'video',
            'api_name' => 'AG',
            'startdate' => date("Y-m-d H:i:s", $startTime - 12 * 60 * 60),
            'enddate' => date("Y-m-d H:i:s", $endTime - 12 * 60 * 60),
            'page' => $page,
            'perpage' => $perpage
        ]);
        $res = $res['data'];
        $result = [];
        if ($res) {
            $code = $res['info'];
            if ($code == 0) {
                if (count($res['row']) == 1) {
                    $tmp = $res['row'];
                    $res['row'] = [];
                    $res['row'][0] = $tmp;
                }
                foreach ($res['row'] as $key => $value) {
                    $subData = [];
                    $attribute = $value['@attributes'];
                    $result[] = $attribute;
                }
                // 拉取剩下的注单
                if ($res['addition']['total'] > $page * $perpage) {
                    $result = array_merge($result, $this->getVideoOrders($startTime, $endTime, $page + 1));
                }
            } else {
                $msg = "AGAPIService->getVideoOrders 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code];
                Log::error($msg);
                error_exit($msg);
            }
        }
        return $result;
    }


    /**
     * 获取捕鱼相关注单
     */
    public function getFishOrders($startTime, $endTime, $page = 1, $perpage = 500)
    {
        $url = config('app.rpcserver') . "/api/getOrders";
        $res = GameApiService::request($url, 'get', [
            'type' => 'fish',
            'api_name' => 'AG',
            'begintime' => $startTime,
            'endtime' => $endTime,
            'page' => $page,
            'numperpage' => $perpage
        ]);
        $res = $res['data'];
        $result = [];
        if ($res) {
            $code = $res['Code'];
            if ($code == 0) {
                if ($res['PageData']['ItemTotal'] == 1) {
                    $tmp = $res['Items'];
                    $res['Items'] = [];
                    $res['Items'][0] = $tmp;
                }
                $result = array_merge($result, $res['Items']);
                // 拉取剩下的注单
                if ($res['PageData']['ItemTotal'] > $page * $perpage) {
                    $result = array_merge($result, $this->getFishOrders($startTime, $endTime, $page + 1));
                }
            } else {
                $msg = "AGAPIService->getFishOrders 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code];
                Log::error($msg);
                error($msg);
            }
        }
        return $result;
    }

    /**
     * 获取养鱼注单
     */
    public function getBuyFish($startTime, $endTime, $page = 1, $perpage = 500)
    {
        $url = config('app.rpcserver') . "/api/getOrders";
        $res = GameApiService::request($url, 'get', [
            'type' => 'buyfish',
            'api_name' => 'AG',
            'begintime' => $startTime,
            'endtime' => $endTime,
            'page' => $page,
            'numperpage' => $perpage,
            'hunted' => 1, // 不用加密
        ]);
        $res = $res['data'];
        $result = [];
        if ($res) {
            $code = $res['Code'];
            if ($code == 0) {
                if ($res['Total'] == 1) {
                    $tmp = $res['Bill'];
                    $res['Bill'] = [];
                    $res['Bill'][0] = $tmp;
                }
                $result = array_merge($result, $res['Bill']);
                // 拉取剩下的注单
                if ($res['Total'] > $page * $perpage) {
                    $result = array_merge($result, $this->getBuyFish($startTime, $endTime, $page + 1));
                }
            } else {
                $msg = "AGAPIService->getBuyFish 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code];
                Log::error($msg);
                error_exit($msg);
            }
        }
        return $result;
    }

    /**
     * 获取游戏类型
     * withlink 包括多台类型 为1的时候查询所有游戏
     * result 说明：
     * gametype : 遊戏类型
     * type: 厅类型, 如 VIDEO 为视频游戏，SLOT 为电子游戏，LOTTO 为彩票游戏
     * gamename: 遊戏类型名称
     */
    public function getGames()
    {
        $url = config('app.rpcserver') . "/api/getGameList";
        $currentData = Game::where(['partner_name' => $this->apiName])->get()->toArray();
        $needUpdate = Redis::set(RedisKeys::AG_LOCK_GAMES, date("Y-m-d H:i:s"), 'nx', 'ex', 3600);
        if (!$currentData || $needUpdate) {
            // 向RPC获取游戏数据
            // 请求数据，如果失败则抛异常
            $res = GameApiService::request($url, 'get', [
                'api_name' => 'AG',
            ]);
            $insertData = [];
            // <row GAMETYPE="23" TYPE="LOTTO" GAMENAME="江西时时彩"/>
            if (empty($res['Code'])) {
                $formatData = [];
                foreach ($currentData as $value) {
                    $formatData[$value['game_type']] = $value;
                }
                $game = [];
                foreach ($res['row'] as $key => $value) {
                    $attribute = $value['@attributes'];
                    if (empty($formatData[$attribute['GAMETYPE']])) {
                        $game['game_type'] = $attribute['GAMETYPE'];
                        $game['type'] = $attribute['TYPE'];
                        $game['game_name'] = $attribute['GAMENAME'];
                        $insertData[] = $game;
                    }
                }
                if (count($insertData) > 0) {
                    DB::table('games')->insert($insertData);
                    if (!$res) {
                        Redis::del(RedisKeys::AG_LOCK_GAMES);
                        $msg = "AG AGAPIService::getGames 保存游戏列表报错失败：" . json_encode($res->getErrors(), JSON_UNESCAPED_UNICODE);
                        Log::error($msg);
                        error_exit($msg);
                    }
                }
                $currentData = array_merge($currentData, $insertData);
            } else {
                $code = $res['Code'];
                $msg = "AGAPIService->getGames 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code];
                Log::error($msg);
                Redis::del(RedisKeys::AG_LOCK_GAMES);
                error_exit($msg);
            }
        }
        $games = [];
        foreach ($currentData as $value) {
            $games[$value['game_type']] = $value;
        }
        return $games;
    }

    /**
     * 获取游戏玩法描述
     * result 说明：
     * playtype : 玩法 ID
     * descripion: 玩法描述
     */
    public function getPlayTypes()
    {
        $currentData = PlayType::get()->toArray();

        $needUpdate = Redis::set(RedisKeys::AG_LOCK_PLAYTYPES, date("Y-m-d H:i:s"), 'nx', 'ex', 3600);
        if (!$currentData || $needUpdate) {
            // 向第三方获取游戏数据

            $url = config('app.rpcserver') . "/api/getGameList";
            $res = GameApiService::request($url, 'get', [
                'api_name' => 'AG',
                'type' => 1
            ]);

            $code = $res['info'];
            if ($code == 0) {
                $formatData = [];
                foreach ($currentData as $value) {
                    $formatData[$value['unique_name']] = $value;
                }
                /**
                 * <info>操作結果</info>
                 * <row playtype ="21" gametype=”DT” descripion ="龙"/>
                 */
                foreach ($res['row'] as $key => $value) {
                    $game = [];
                    $attribute = $value['@attributes'];
                    $uniqueName = $attribute['gametype'] . "_" . $attribute['playtype'];
                    if (empty($formatData[$uniqueName])) {
                        $game['game_type'] = $attribute['gametype'];
                        $game['play_type'] = $attribute['playtype'];
                        $game['description'] = $attribute['description'];
                        $game['unique_name'] = $uniqueName;
                        $insertData[] = $game;
                    }
                }
                if (count($insertData) > 0) {
                    DB::table('playtypes')->insert($insertData);
                    if (!$res) {
                        Redis::del(RedisKeys::AG_LOCK_PLAYTYPES);
                        $msg = "AG AGAPIService::getPlayTypes 保存游戏列表报错失败：" . json_encode($res->getErrors(), JSON_UNESCAPED_UNICODE);
                        Log::error($msg);
                        error_exit($msg);
                    }
                }
                $currentData = array_merge($currentData, $insertData);
            } else {
                $msg = "AGAPIService->getPlayTypes 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code];
                Log::error($msg);
                Redis::del(RedisKeys::AG_LOCK_PLAYTYPES);
                error_exit($msg);
            }
        }
        $playTypes = [];
        foreach ($currentData as $value) {
            $uniqueName = $value['game_type'] . "_" . $value['play_type'];
            $playTypes[$uniqueName] = $value;
        }
        return $playTypes;
    }

    /**
     * 额度记录类型
     * result:
     * transtype: 额度操作类型标识
     * descripion: 额度操作类型描述
     */
    public function getTransTypes()
    {
        $url = $this->api_url . "/gettranstypes.xml";
        $data = [
            'cagent' => $this->cagent,
            'language' => $this->language,
        ];
        $response = $this->request($url, 'get', $data);
        $res = $response->getData();
        /**
         * <result>
         * <info>操作結果</info>
         * <row transtype ="RECALC" descripion ="重新派彩"/>
         * </result>
         */
        Log::info($res);
        exit;
        if ($response->isOk) {
            // todo test, add to sql
            $code = $res['info'];
            if ($code == 0) {
                $result = [];
            } else {
                BaseHandler::error("AGAPIService->getTransTypes 请求返回不成功： code: {$code}, msg: " . self::$ErrorMsg[$code]);
            }
        }
    }

    /**
     * 获取注单统计，每日的统计
     */

    /**
     * 获取转账额度记录
     */
}